﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Swan.SwanWakeUp.Controls
{
    /// <summary>
    /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
    ///
    /// Step 1a) Using this custom control in a XAML file that exists in the current project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Swan.SwanWakeUp.Controls"
    ///
    ///
    /// Step 1b) Using this custom control in a XAML file that exists in a different project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Swan.SwanWakeUp.Controls;assembly=Swan.SwanWakeUp.Controls"
    ///
    /// You will also need to add a project reference from the project where the XAML file lives
    /// to this project and Rebuild to avoid compilation errors:
    ///
    ///     Right click on the target project in the Solution Explorer and
    ///     "Add Reference"->"Projects"->[Browse to and select this project]
    ///
    ///
    /// Step 2)
    /// Go ahead and use your control in the XAML file.
    ///
    ///     <MyNamespace:CustomControl1/>
    ///
    /// </summary>
    public class NumericUpDown : TextBox
    {
        private Polygon downArrow;
        private Polygon upArrow;
        private TextBox textBox;



        public int MaxValue
        {
            get { return (int)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxValueProperty =
            DependencyProperty.Register("MaxValue", typeof(int), typeof(NumericUpDown), new PropertyMetadata(0));



        public int MinValue
        {
            get { return (int)GetValue(MinValueProperty); }
            set { SetValue(MinValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MinValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinValueProperty =
            DependencyProperty.Register("MinValue", typeof(int), typeof(NumericUpDown), new PropertyMetadata(0));



        public int Value
        {
            get 
            {
                return (int)GetValue(ValueProperty); 
            }
            set 
            {
                if (value > MaxValue)
                    value = MaxValue;
                else if (value < MinValue)
                    value = MinValue;

                this.Text = value.ToString();
                textBox.Text = value.ToString();
                SetValue(ValueProperty, value); 
            }
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown), null);


        static NumericUpDown()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
        }

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            this.Value += e.Delta / 120;
            base.OnMouseWheel(e);
        }

        public override void OnApplyTemplate()
        {
            downArrow = base.GetTemplateChild("downArrow") as Polygon;
            downArrow.MouseDown += downArrow_MouseDown;
            upArrow = base.GetTemplateChild("upArrow") as Polygon;
            upArrow.MouseUp += upArrow_MouseUp;
            textBox = base.GetTemplateChild("textBox") as TextBox;
            textBox.TextChanged += textBox_TextChanged;
            base.OnApplyTemplate();
        }

        void textBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            int value;
            this.Value = int.TryParse(textBox.Text, out value) ? value : 0;
        }

        void upArrow_MouseUp(object sender, MouseButtonEventArgs e)
        {
            this.Value++;
        }

        void downArrow_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.Value--;
        }
    }
}
